package br.com.amethyst.workflow;

import java.io.FileOutputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import br.com.amethyst.workflow.exception.WorkflowProcessException;
import br.com.amethyst.workflow.exception.WorkflowSourceValidationException;
import br.com.amethyst.workflow.source.IWorkflowSource;
import br.com.amethyst.workflow.template.ITemplate;

/**
 * Workflow processor
 * Can convert different types of {@link IWorkflowSource} patterns.
 * Receive a workflow source and a Template source that is the responsable to
 * convert the workflow from one pattern to another. Also it's possible validates
 * if the workflow source is correctly build through XSD Schema check.
 * 
 * @author Artur Figueira <arturfigueira@gmail.com>
 * @see IWorkflowSource
 * @see ITemplate
 */
public class WorkflowProcessor 
{
	private boolean validate = true;
	
	/**
	 * Default constructor
	 */
	public WorkflowProcessor(){	}	
	
	/**
	 * Create an instance of the processor setting if the 
	 * Workflow processing will validate the source
	 * @param validateSource Set if the processing will validate or not the source
	 */
	public WorkflowProcessor(boolean validateSource)
	{
		this.validate = validateSource;
	}	
		
	/**
	 * Process a given {@link IWorkflowSource} based into a {@link ITemplate} outputting the 
	 * result of the operation into a desired location
	 * 
	 * @param workflowSource Workflow from a pattern
	 * @param templateSource Template used to convert the workflow to another pattern
	 * @param outputFilePath The destination of the processing
	 * @throws WorkflowProcessException
	 * @throws WorkflowSourceValidationException 
	 */
	public void process(IWorkflowSource workflowSource, ITemplate templateSource, String outputFilePath) throws WorkflowProcessException, WorkflowSourceValidationException
	{
		try{
			//Create a new instance of TransformerFactory...it depends of the system...
			TransformerFactory tFactory = TransformerFactory.newInstance();
			
			//..thru this factory  create a new Transformer factory using as source the TemplateSource
			Transformer transformer = tFactory.newTransformer(templateSource.getSource());
			
			//Case this source is not valid (based on it's XSD Schema) throw a Validation Exception
			if(validate && !workflowSource.doValidate())
				throw new WorkflowSourceValidationException("The loaded WorkflowSource is not correctly formatted, based on it's Pattern Schema");
				
			//Transform the WorkflowSource based on the Template setup just above
			transformer.transform(workflowSource.getSource(), new StreamResult(new FileOutputStream(outputFilePath)));
		}
		catch (WorkflowSourceValidationException e) {
			throw e;
		}
		catch (Exception e){
			throw new WorkflowProcessException(e.getMessage());
		}
	}
	
	/**
	 * Set to not validate the workflow source file
	 */
	public void noValidation(){
		this.validate = false;
	}
	
	/**
	 * Set to if it'll or not validate the workflow source file
	 */
	public void setValidate(boolean validate){
		this.validate = validate;
	}
}
